#include "include.h"

extern u8 eq_rx_buf[EQ_BUFFER_LEN];
const u16 bt_key_msg_tbl[6] = {
    KU_PLAY,
    KU_PREV,
    KU_NEXT,
    KU_VOL_DOWN,
    KU_VOL_UP,
    KU_MODE,
};
#if BT_SCO_DBG_EN
void bsp_aec_ack_param(void)
{
    u8 buf[11];
    buf[0] = 'a';
    buf[1] = 'e';
    buf[2] = 'c';
    buf[3] = f_bt.mic_anl_gain;
    buf[4] = f_bt.mic_dig_gain;
    buf[5] = 0;
    buf[6] = (u8)f_bt.noise;
    buf[7] = (u8)(f_bt.noise >> 8);
    buf[8] = f_bt.aec_level;
    buf[9] = f_bt.aec_offset;
    bt_spp_tx(buf, 11);
}

void bsp_aec_ack(void)
{
    u8 buf[6];
    buf[0] = 'a';
    buf[1] = 'e';
    buf[2] = 'c';
    buf[3] = ' ';
    buf[4] = 'o';
    buf[5] = 'k';
    bt_spp_tx(buf, 6);
}
#endif

void bsp_app_0_process(u8 *ptr, u16 size)
{
#if EQ_DBG_IN_SPP
    if (xcfg_cb.eq_dgb_spp_en) {
        eq_spp_cb_t *p = &eq_dbg_cb.eq_spp_cb;
        if ((ptr[0] == 'E' && ptr[1] == 'Q') || (ptr[0] == 'D' && ptr[1] == 'R')) {       //EQ消息
            if (ptr[2] == '?') {
                memcpy(eq_rx_buf, ptr, size);
                msg_enqueue(EVT_ONLINE_SET_EQ);
                return;
            }
            u32 rx_size = little_endian_read_16(ptr, 4) + 6;
            memcpy(eq_rx_buf, ptr, size);
            p->rx_size = rx_size;
            if (size < rx_size) {
                p->remain = 1;
                p->remian_ptr = size;
            } else {
                p->remain = 0;
                p->remian_ptr = 0;
                msg_enqueue(EVT_ONLINE_SET_EQ);
            }
            return;
        }
        if (p->remain) {
            memcpy(&eq_rx_buf[p->remian_ptr], ptr, size);
            p->remian_ptr += size;
            if (p->rx_size == p->remian_ptr) {
                msg_enqueue(EVT_ONLINE_SET_EQ);
                memset(p, 0, sizeof(eq_spp_cb_t));
            }
            return;
        }
    }
#endif

#if BT_SCO_DBG_EN
    if (ptr[0] == 'a' && ptr[1] == 'e' && ptr[2] == 'c') {
        u8 cnt, i;
        if (ptr[3] == '?') {
            bsp_aec_ack_param();
            return;
        }
        cnt = 3;
        for (i = 0; i < 6; i++) {
            u16 value;
            if (i == AEC_PARAM_NOISE) {   //第3个参数2Byte
                value = ptr[cnt++];
                value |= ptr[cnt++] << 8;
            } else {
                value = ptr[cnt++];
            }
            sco_audio_set_param(i, value);
        }
        bsp_aec_ack();
        return;
    }
#endif
#if 0
    my_printf("%s, spprx_data_buf: ", __func__);
    for (int i = 0; i < size; i++)
    {
        my_printf("%02x ", ptr[i]);
    }
    my_printf("\n");
#endif
    switch (ptr[0]) {
        case 0x01:
            //system control
            if (size != 4) {
                return;     //2byte data + 2byte crc16
            }
            if ((ptr[1] > 0) && (ptr[1] <= sizeof(bt_key_msg_tbl))) {
                msg_enqueue(bt_key_msg_tbl[ptr[1] - 1]);
            }
            break;

        case 0x02:
            //rgb leds control
            if (size != 7) {
                return;     //5byte data + 2byte crc16
            }
#if PWM_RGB_EN
            if (ptr[1] > 0) {
                pwm_rgb_write(ptr[2], ptr[3], ptr[4]);
            } else {
                pwm_rgb_close();
            }
#endif // PWM_RGB_EN
            break;

        case 0x03:
            //ota control
            break;
    }
}

static int bsp_spp_uart_bypass(uint8_t *packet, uint16_t size)
{
    iodm_spp_protocol_frame_response(packet, size);
    return 0;
}

typedef struct {
    uint8_t rx_buf[1024];
    uint16_t len;
    bool feed;
    uint32_t timeout;  // 添加时间戳字段用于超时检测
} bsp_sppmgr_t;

static bsp_sppmgr_t g_bsp_sppmgr = {
    .rx_buf = {0},
    .len = 0,
    .feed = false,
    .timeout = 100,
};

void bsp_sppmgr_reset(void)
{
    memset(g_bsp_sppmgr.rx_buf, 0, sizeof(g_bsp_sppmgr.rx_buf));
    g_bsp_sppmgr.len = 0;
    g_bsp_sppmgr.feed = false;
}

static void bsp_spp_data_enqueue(uint8_t *packet, uint16_t size)
{
    if (size > sizeof(g_bsp_sppmgr.rx_buf))
        return;
#if 1
    if (!g_bsp_sppmgr.feed)
    {
        memcpy(g_bsp_sppmgr.rx_buf, packet, size);
        g_bsp_sppmgr.len = size;
        g_bsp_sppmgr.feed = true;
        msg_enqueue(EVT_SPP_DATA_REPORT);
    }
#else
    while(1)
    {
        if (!g_bsp_sppmgr.feed)
            break;

        g_bsp_sppmgr.timeout--;
        if (g_bsp_sppmgr.timeout == 0)
        {
            g_bsp_sppmgr.timeout = 100;
            break;
        }

        delay_ms(1);
    }

    memcpy(g_bsp_sppmgr.rx_buf, packet, size);
    g_bsp_sppmgr.len = size;
    g_bsp_sppmgr.feed = true;
    msg_enqueue(EVT_SPP_DATA_REPORT);

#endif

    return ;
}

int bsp_spp_data_handle(void)
{
    if (!g_bsp_sppmgr.feed)
        return -1;

    bsp_spp_uart_bypass(g_bsp_sppmgr.rx_buf, g_bsp_sppmgr.len);
    bsp_sppmgr_reset();
    return 0;
}

void spp_rx_callback(uint8_t *packet, uint16_t size)
{
#if FOT_EN
    if (fot_app_connect_auth(packet, size)) {
        fot_recv_proc(packet, size);
        return;
    }
#endif
#if BT_SPP_EN
    bsp_app_0_process(packet, size);
#endif // BT_SPP_EN
#if 0
    bsp_spp_uart_bypass(packet, size);
#else
    bsp_spp_data_enqueue(packet, size);
#endif
}

void spp_connect_callback(void)
{
    my_printf("--->spp_connect_callback\n");
    msg_enqueue(EVT_SPP_CONNECT);
    // if (bsp_bt_mgr_mfi_status_get())
    // {
    //     iodm_protocol_frame_response(CMD_REPORT_SPP_CONNECT, 16, bsp_bt_mgr_mfi_uuid_get());
    // }

#if 0
    /* carplay iap2 protocol test: when carplay connnect 2 iphone
     * send iap2 data to iphone, iphone will reponse same data
     * to spp rx buf
     * */
    u8 iap2_buf[6] = {0xFF, 0x55, 0x02, 0x00, 0xEE, 0x10};
    bt_spp_tx(iap2_buf, sizeof(iap2_buf));
#endif
#if FOT_EN
    fot_spp_connect_callback();
#endif
}

void spp_disconnect_callback(void)
{
    my_printf("--->spp_disconnect_callback\n");
    // iodm_protocol_frame_response(CMD_REPORT_SPP_DISCONNECT, 0, NULL);
#if FOT_EN
    fot_spp_disconnect_callback();
#endif
}

void bsp_spp_connect_handle(void)
{
    if (bsp_bt_mgr_mfi_status_get())
    {
        iodm_protocol_frame_response(CMD_REPORT_SPP_CONNECT, 16, bsp_bt_mgr_mfi_uuid_get());
    }
}
